# Ce qui suit un dièze n'est pas exécuté. On appelle ça un commentaire.
# Les trois commandes seront comprises par le code
10+2 [1] 12
10 + 2 [1] 12
10 + 2[1] 12
(tableaux excel fournis pour la matinée)
R est un langage de programmation open source spécialisé dans la statistique et l’analyse des données. Il a été créé pour fournir un environnement convivial pour la manipulation, l’analyse et la visualisation des données.Il existe d’autres langages de programmation comme Python, JavaScript, Java, C++ etc.
R est utilisé pour effectuer des opérations statistiques, ajuster des modèles, créer des graphiques et effectuer des analyses de données complexes.
R est extrêmement flexible et extensible grâce à des packages R, qui ajoutent des fonctionnalités supplémentaires.
RStudio est un environnement de développement intégré (IDE) conçu spécifiquement pour travailler avec le langage R. C’est un logiciel qui fournit une interface utilisateur plus conviviale pour écrire, exécuter et gérer des scripts R.
RStudio inclut un éditeur de texte avec coloration syntaxique, un gestionnaire de packages, des fenêtres pour l’affichage des graphiques et des données, et bien d’autres fonctionnalités pour améliorer la productivité des utilisateurs R.
En résumé, R est le langage de programmation sous-jacent pour l’analyse des données, tandis que RStudio est un environnement de développement qui facilite l’utilisation de R.
Il existe de plusieurs ressources en français pour apprendre à coder sur R. Nous vous recommandons en particulier :
Les bonnes ressources anglophones gratuites sont très nombreuses, très faciles à trouver sur le Web. Le grand classique est R for data science, de Grolemund et Wickham [-@grolemund2022]. On se focalise ici avec deux autres qui sont le plus en lien avec nos sujets :
N’hésitez pas à chercher directement sur le Web en cas de problème. Vous serez souvent conduits vers les forums stackoverflow ou RStudio, qui sont aussi des ressources très précieuses pour résoudre des problèmes très spécifiques.
Pour vous retrouver parmi la multitude de packages existants, il existe une autre ressource précieuse en ligne qui pourra vous orienter méthodologiquement en fonction de votre domaine de recherche. Il s’agit de CRAN Task View : https://cran.r-project.org/web/views/.
Les vues de tâches CRAN visent à fournir des recommandations sur les packages présents sur CRAN qui sont adaptés à un sujet spécifique. Elles donnent un bref aperçu des packages inclus, qui peuvent également être installés automatiquement à l’aide du package ctv. Les vues ont pour but d’avoir un focus bien défini de manière à ce qu’il soit suffisamment clair quels packages devraient être inclus (ou exclus) - et elles ne visent pas à recommander les “meilleurs” packages pour une tâche donnée.
Faire un point sur le cheat sheet (?URL) et ouverture du cheat-sheet base de R : https://iqss.github.io/dss-workshops/R/Rintro/base-r-cheat-sheet.pdf
[Interface de Rstudio] (R_interface_colored.png)
A : fenêtre script/source B : console C : environnement D : explorateur
La fenêtre de script permet d’éditer les fichiers scripts en vue d’éxécuter le code.
La console est la fênetre où s’éxécute le code et où on peut directement taper des commandes. Il n’est pas obligatoire de passer par la fenêtre de script.
L’environnement rassemble des fonctionnalités pour suivre le fonctionnement de R, en faisant notamment apparaître les différents objets générés par notre script.
L’explorateur permet de connaître les fichiers de notre ordinateur, de visualiser les rendus graphiques et cartographiqus, les différentes librairies et l’aide pour l’utilisation de ces dernières.
On se focalise ici sur quelques aspects qui peuvent être requis pour la manipulation du code et à la marge.
Lorsqu’on saisit une commande, que ce soit dans la console ou dans la fenêtre de script, les espaces autour des opérateurs n’ont pas d’importance.
Les trois commandes suivantes sont donc équivalentes, mais on privilégie en général la deuxième pour des raisons de lisibilité du code.
# Ce qui suit un dièze n'est pas exécuté. On appelle ça un commentaire.
# Les trois commandes seront comprises par le code
10+2 [1] 12
10 + 2 [1] 12
10 + 2[1] 12
Pour les opérations plus complexes, il faut veiller à utiliser les parenthèses, sinon les résultats ne seront pas corrects :
10 + 2 * 5 / 14 - 2 * 2 [1] 6.714286
(10 + (2*5)) / (14 - (2 * 2)) [1] 2
Le signe <- correspond à l’assignation d’une valeur à une variable dont on choisit le nom.
# On commence par faire une opération simple
3 + 4[1] 7
# Ce qui équivaut à :
a <- 3
b <- 4
a + b[1] 7
# Et on peut également stocker le résultat dans une nouvelle variable
c <- a + b
c[1] 7
Du fait de l’assignation “<-”, les valeurs sont automatiquement associées à l’objet et ce dernier apparaît dans la fenêtre environnement.
De manière générale, vous allez retrouver dans cette fenêtre tous les objets que vous avez créés après éxécution du code : que ce soit de simples variables, des tableaux, des fonctions, des objets graphiques, etc.
Quand on assigne une nouvelle valeur à un objet déjà existant, la valeur précédente est perdue. Les objets n’ont pas de mémoire.
x <- 2
x <- 5
x[1] 5
#> [1] 5Les objets peuvent contenir tout un tas de données. Jusqu’ici on n’a stocké que des nombres, mais ils peuvent aussi contenir des chaînes de caractères (du texte), qu’on délimite avec des guillemets simples ou doubles (’ ou “) :
chien <- "Chihuahua"
chien[1] "Chihuahua"
#> [1] "Chihuahua"Ici la variable “chien” est un objet contenant une chaîne de caractères.
Un point important est relatif aux types des variables : numérique, catégorielles, textes, dates, spatiales… En général, les opérations ne peuvent concerner que des variables du même type. Les fonctions sont souvent contraignantes quant aux types des variables qu’elles prennent comme arguments.
# Exemple avec une variable numérique et une variable caractère
x <- 5
y <- "hello"
# Tentative d'addition de deux variables de types différents
#resultat <- x + yLes vecteurs permettent de stocker des informations de même nature dans un unique objet. Exemple :
# Si on continuait à créer des objets ponctuels :
taille1 <- 156
taille2 <- 164
taille3 <- 197
taille4 <- 147
taille5 <- 173
(taille1 + taille2 + taille3 + taille4 + taille5) / 5[1] 167.4
#> [1] 167.4Précédemment, nous avons stockés différentes valeurs chiffrées sous plusieurs objets qui apparaissent dans notre fenêtre d’environnement.
tailles <- c(156, 164, 197, 147, 173)
#> [1] 156 164 197 147 173Un vecteur dans R est un objet qui peut contenir plusieurs informations du même type, potentiellement en très grand nombre.
Ici la variable “tailles”est un vecteur contenant des valeurs chiffrées.
Ce qui est pratique avec les vecteurs, c’est qu’on peut alors leur appliquer des opérations qui s’appliqueront à l’ensemble des valeurs du vecteur.
Exercice : taille en mètres
# Si l'on souhaite la taille en mètres :
tailles / 100 [1] 1.56 1.64 1.97 1.47 1.73
#> [1] 1.56 1.64 1.97 1.47 1.73
tailles_m <- tailles / 100
tailles_m[1] 1.56 1.64 1.97 1.47 1.73
#> [1] 1.56 1.64 1.97 1.47 1.73Cela fonctionne pour toutes les opérations de base :
tailles + 10[1] 166 174 207 157 183
#> [1] 166 174 207 157 183
tailles^2[1] 24336 26896 38809 21609 29929
#> [1] 24336 26896 38809 21609 29929Exercice : calculer l’IMC (diviser le poids en kilo par la taille en mètre) à partir des valeurs suivantes
#Indice de l'IMC :
tailles <- c(156, 164, 197, 147, 173)
# exercice : talons 10 cms
# connaître le ratio taille/poids
# une opération à tout un vecteur se réexécute
poids <- c(45, 59, 110, 44, 88)On crée l’objet imc :
imc <- poids / (tailles / 100) ^ 2
imc[1] 18.49112 21.93635 28.34394 20.36189 29.40292
#> [1] 18.49112 21.93635 28.34394 20.36189 29.40292# On commence par créer les variables (les colonnes du tableau)
noms <- c("John", "Jack", "Cindy", "Samantha")
sexe <- c("homme", "homme", "femme", "femme")
ages <- c(42, 57, 24, NA)
poids <- c(87, 73, NA, NA)
tailles <- c(174, 198, 192, 164)
# On les rassemble dans un tableau
ma_table <- data.frame(noms, sexe, ages, poids, tailles)Les noms d’objets peuvent contenir des lettres, des chiffres, les symboles . et _. Ils ne peuvent pas commencer par un chiffre. Attention, R fait la différence entre minuscules et majuscules dans les noms d’objets, ce qui signifie que x et X seront deux objets différents, tout comme resultat et Resultat.
De manière générale, il est préférable d’éviter les majuscules (pour les risques d’erreur) et les caractères accentués (pour des questions d’encodage) dans les noms d’objets.
De même, il faut essayer de trouver un équilibre entre clarté du nom (comprendre à quoi sert l’objet, ce qu’il contient) et sa longueur. Par exemple, on préfèrera comme nom d’objet taille_conj1 à taille_du_conjoint_numero_1 (trop long) ou à t1 (pas assez)
R est constitué de fonctions. De nombreuses fonctions prédéfinies sont contenues dans la base de R ou dans des packages qu’on ajoute (que l’on verra plus tard). La meilleure manière de comprendre ce qu’est une fonction est d’en créer une soi même.
# On crée une fonction "ajoute" qui prend deux paramètres.
# x est un premier et y est celui qu'on ajoute
ajoute <- function(x, y) {
x + y
}
# On peut maintenant utiliser cette fonction
ajoute(3, 4)[1] 7
# On peut effectuer les mêmes opérations. Les valeurs a et b sont encore
# en mémoire, donc on peut faire :
ajoute(a, b)[1] 7
c <- ajoute(a, b)
c[1] 7
ajoute(c, a)[1] 10
Exercice : rendre lisible le code ci-dessous
x <- 5*(3+2)-1
if(x%%2==0) {print('Pair')} else{print('Impair')}[1] "Pair"
for(i in 1:10) {if(i%%2 == 0) {print(paste('Nombre pair :', i))} else{print(paste('Nombre impair :', i))}}[1] "Nombre impair : 1"
[1] "Nombre pair : 2"
[1] "Nombre impair : 3"
[1] "Nombre pair : 4"
[1] "Nombre impair : 5"
[1] "Nombre pair : 6"
[1] "Nombre impair : 7"
[1] "Nombre pair : 8"
[1] "Nombre impair : 9"
[1] "Nombre pair : 10"
Code corrigé :
# Calcul de x
x <- 5 * (3 + 2) - 1
# Vérification de la parité de x
if (x %% 2 == 0) {
print('x est pair')
} else {
print('x est impair')
}[1] "x est pair"
# Boucle pour les nombres de 1 à 10
for (i in 1:10) {
if (i %% 2 == 0) {
print(paste('Nombre pair :', i))
} else {
print(paste('Nombre impair :', i))
}
}[1] "Nombre impair : 1"
[1] "Nombre pair : 2"
[1] "Nombre impair : 3"
[1] "Nombre pair : 4"
[1] "Nombre impair : 5"
[1] "Nombre pair : 6"
[1] "Nombre impair : 7"
[1] "Nombre pair : 8"
[1] "Nombre impair : 9"
[1] "Nombre pair : 10"
na.rm : Les valeurs manquantes, notées NA dans R (certaines peuvent avoir pour valeur NaN). On utilise na.rm pour les éluder dans les opérations simples.
# On peut reprend le jeu de données ma_table
# On peut faire une moyenne sur les tailles car on a toutes les variables
mean(ma_table$tailles)[1] 182
sum(ma_table$tailles)[1] 728
# Mais la moyenne ne fonctionne pas immédiatement sur les poids ou les âges
# car il manque des variables
mean(ma_table$ages)[1] NA
sum(ma_table$poids)[1] NA
# Il faut préciser qu'il faut omettre les variables manquantes
mean(ma_table$ages, na.rm = TRUE)[1] 41
sum(ma_table$poids, na.rm = TRUE)[1] 160
Le “tidyverse” st un ensemble cohérent de packages R conçus pour la manipulation, la visualisation et l’analyse de données de manière cohérente et efficace. Il a été développé pour simplifier le flux de travail de l’analyse de données et pour rendre le code plus lisible et plus facile à comprendre.
Le signe %>% est un “tuyau”. On peut le lire à haute voix comme “ensuite”. Par exemple :
library(tidyverse)Warning: le package 'tidyverse' a été compilé avec la version R 4.2.3
Warning: le package 'ggplot2' a été compilé avec la version R 4.2.3
Warning: le package 'tibble' a été compilé avec la version R 4.2.3
Warning: le package 'tidyr' a été compilé avec la version R 4.2.3
Warning: le package 'readr' a été compilé avec la version R 4.2.3
Warning: le package 'purrr' a été compilé avec la version R 4.2.3
Warning: le package 'dplyr' a été compilé avec la version R 4.2.3
Warning: le package 'stringr' a été compilé avec la version R 4.2.3
Warning: le package 'forcats' a été compilé avec la version R 4.2.3
Warning: le package 'lubridate' a été compilé avec la version R 4.2.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.2 ✔ readr 2.1.4
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ ggplot2 3.4.2 ✔ tibble 3.2.1
✔ lubridate 1.9.2 ✔ tidyr 1.3.0
✔ purrr 1.0.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
d <- a %>%
ajoute(b) %>%
ajoute(c)Le “tidyverse” comprend plusieurs packages populaires, et notamment,dplyr. Ce dernier est très utile pour épurer les données lorsque vous travaillez sur des tableaux (et donc sur des tables attributaires).
Il est utilisé pour la manipulation de données, notamment le filtrage, la sélection, le regroupement et la création de nouvelles variables.
# Un exemple qui combine ces opérations
ma_table %>%
filter(!is.na(ages)) noms sexe ages poids tailles
1 John homme 42 87 174
2 Jack homme 57 73 198
3 Cindy femme 24 NA 192
#consulter la sortie de l'objet
ma_table %>%
filter(!is.na(ages)) %>%
select(sexe, ages, tailles, poids) sexe ages tailles poids
1 homme 42 174 87
2 homme 57 198 73
3 femme 24 192 NA
ma_table %>%
filter(!is.na(ages)) %>%
select(sexe, ages, tailles, poids) %>%
group_by(sexe) %>%
summarise(nb_pers = n())# A tibble: 2 × 2
sexe nb_pers
<chr> <int>
1 femme 1
2 homme 2
ma_table %>%
filter(!is.na(ages)) %>%
select(sexe, ages, tailles, poids) %>%
group_by(sexe) %>%
summarise(nb_pers = n(),
somme_poids = sum(poids, na.rm = TRUE),
taille_max = max(tailles, na.rm = TRUE),
age_moy = mean(ages, na.rm = TRUE))# A tibble: 2 × 5
sexe nb_pers somme_poids taille_max age_moy
<chr> <int> <dbl> <dbl> <dbl>
1 femme 1 0 192 24
2 homme 2 160 198 49.5
Pour comprendre l’intérêt du tidyverse, voici le même tableau sans l’opérateur pipe :
filtered_table <- filter(ma_table, !is.na(ages))
selected_cols <- select(filtered_table, sexe, ages, tailles, poids)
grouped_table <- group_by(selected_cols, sexe)
summary_table <- summarise(grouped_table,
nb_pers = n(),
somme_poids = sum(poids, na.rm = TRUE),
taille_max = max(tailles, na.rm = TRUE),
age_moy = mean(ages, na.rm = TRUE)
)On est contraints à créer beaucoup plus de variables comme intermédiaires de calcul (selected_cols, grouped_table, summary_table)
Voici certaines de fonctions fondamentales du dplyr : - select : choisir des colonnes - filter : choisir des lignes - mutate : modifier des valeurs - group_by : variables pour des tris - créer des filtres : summarise
Exercice : après avoir visualisé le tableau suivant, re-coder les opérations ci-dessous en utilisant le tidyverse :
Sélectionnez uniquement les colonnes produit, quantite, et prix_unitaire du data frame ventes_magasin.
Filtrez les lignes du data frame pour ne conserver que les ventes où la quantité vendue est supérieure à 5 unités.
Ajoutez une nouvelle colonne nommée montant qui représente le montant total de chaque vente (quantité multipliée par le prix unitaire) et ajoutez-la au data frame.
Regroupez les données par produit pour calculer la quantité totale vendue de chaque produit.
Filtrez les produits pour ne conserver que ceux dont la quantité totale vendue est supérieure à 100 unités.
# Création du data frame ventes_magasin
ventes_magasin <- data.frame(
produit = c("Produit A", "Produit B", "Produit A", "Produit C", "Produit B", "Produit A", "Produit C", "Produit B", "Produit A"),
quantite = c(8, 4, 12, 6, 7, 9, 3, 11, 5),
prix_unitaire = c(10, 15, 8, 12, 20, 10, 18, 14, 9),
date_vente = as.Date(c("2023-01-05", "2023-01-08", "2023-01-09", "2023-01-10", "2023-01-15", "2023-01-20", "2023-01-25", "2023-01-30", "2023-02-02"))
)
# # Étape 1 : Sélectionnez uniquement les colonnes produit, quantite et prix_unitaire
# ventes_magasin <- ventes_magasin[c("produit", "quantite", "prix_unitaire")]
#
# # Étape 2 : Filtrez les ventes où la quantité vendue est supérieure à 5 unités
# ventes_magasin <- ventes_magasin[ventes_magasin$quantite > 5, ]
#
# # Étape 3 : Ajoutez une colonne montant
# ventes_magasin$montant <- ventes_magasin$quantite * ventes_magasin$prix_unitaire
#
# # Étape 4 : Regroupez par produit et calculez la quantité totale vendue
# ventes_par_produit <- aggregate(quantite ~ produit, data = ventes_magasin, FUN = sum)
#
# # Étape 5 : Filtrez les produits avec une quantité totale vendue supérieure à 100 unités
# ventes_par_produit <- ventes_par_produit[ventes_par_produit$quantite_totale > 100, ]
#
# # Étape 6 : Résumez les données
# ventes_par_produit <- aggregate(cbind(quantite, montant) ~ produit, data = ventes_magasin, FUN = function(x) c(sum = sum(x), nombre_ventes = length(x)))Réponse :
library(dplyr)
# Étape 1 : Sélectionnez uniquement les colonnes produit, quantite, et prix_unitaire
ventes_magasin <- ventes_magasin %>%
select(produit, quantite, prix_unitaire)
# Étape 2 : Filtrez les ventes où la quantité vendue est supérieure à 5 unités
ventes_magasin <- ventes_magasin %>%
filter(quantite > 5)
# Étape 3 : Ajoutez une colonne montant
ventes_magasin <- ventes_magasin %>%
mutate(montant = quantite * prix_unitaire)
# Étape 4 : Regroupez par produit et calculez la quantité totale vendue
ventes_par_produit <- ventes_magasin %>%
group_by(produit) %>%
summarise(quantite_totale = sum(quantite))
# Étape 5 : Filtrez les produits avec une quantité totale vendue supérieure à 100 unités
ventes_par_produit <- ventes_par_produit %>%
filter(quantite_totale > 100)
# Étape 6 : Résumez les données
ventes_par_produit <- ventes_magasin %>%
group_by(produit) %>%
summarise(
quantite_totale = sum(quantite),
montant_total = sum(montant),
nombre_ventes = n()
)Certaines opérations particulières requièrent des connaissances plus approfondies.
Jointures : fusionner deux tableaux par une variable d’identification (“clé”)
# Tableau clients
clients <- data.frame(ID = c(1, 2, 3, 4),
nom_client = c("Alice", "Bob", "Charlie", "David"))
# Tableau commandes
commandes <- data.frame(ID = c(2, 3, 1, 4),
montant = c(100, 150, 50, 200))
# Jointure par ID
resultat <- inner_join(clients, commandes, by = "ID")Cette opération exige toutefois que la variable d’identification soit écrite de manière identique dans les deux jeux de données.
Supposons que l’on travaille sur les aires protégées à Madagascar et que l’on dispose de deux jeux de données provenant de sources différentes. On a alors des informations complémentaires que l’on souhaite fusionner en un seul tableau via le nom de l’aire protégée.
Il faudra veiller à ce que les noms aient la même écriture (pas de différences avec des majuscules, des abréviations ou des noms raccourcis)
Les données tabulaires peuvent être structurées de deux manières différentes, généralement appelées format long et format large.
La plupart des gens sont plus familiers avec le format large, car c’est le format que nous, en tant qu’humains, utiliserions naturellement pour structurer nos données lorsque nous travaillons avec des feuilles de calcul, par exemple dans Excel.
Dans le format large, l’identifiant d’une observation est inclus exactement une fois et ne se répète pas (voir Tableau A).
Dans le format long, l’identifiant ainsi que d’autres variables de qualification peuvent être répétés plusieurs fois pour identifier de manière unique chaque observation dans une seule ligne (voir Tableau B).
Fig. 1 : Exemple d’un tableau large (A) et long (B) contenant les mêmes données.
Le format long est souvent nécessaire lors de l’interaction avec des ordinateurs, par exemple pour créer des graphiques avec ggplot2.
Le contenu des deux formats est exactement le même, c’est juste que l’un est plus convivial pour les humains que pour les ordinateurs.
Si vous êtes familiers avec le tidyverse de R, vous avez peut-être aussi entendu parler du terme données bien structurées.
En ce qui concerne les données tabulaires, vous pouvez imaginer que les données bien structurées font référence à des données dans un tableau long qui remplit naturellement les exigences suivantes :
Le Tableau A, en ce sens, n’est pas propre puisque la variable de l’année n’est pas présente dans sa propre colonne, mais au lieu de cela, elle est répartie dans deux colonnes différentes. Le Tableau B est un format long où chaque variable est présente dans exactement une colonne. En ce sens, chaque ligne individuelle représente exactement une observation, c’est-à-dire l’observation d’un pays spécifique pour une année spécifique.
# Création d'un tableau long
# Création de vecteurs pour les années, les pays et les valeurs
annees <- c(2000, 2001)
pays <- c("Argentina", "Brasil", "Chile")
valeurs_ex <- c(1723, 1823, 1353, 1592, 506, 602)
df_long <- data.frame(Annee = annees, Pays = pays, Valeur = valeurs_ex)
# Transformation en format large avec pivot_wider
df_wide <- pivot_wider(df_long, names_from = Pays, values_from = Valeur)
# Création d'un tableau large
# Création de la matrice (alias liste de vecteurs) pour les valeurs X
valeurs_ex <- matrix(c(
1723, 1823,
1353, 1592,
506, 602
), nrow = 3, byrow = TRUE) # Assurez-vous que les valeurs sont dans le bon ordre
df_large <- data.frame(Annee = annees, Argentina = valeurs_ex[1, ], Brasil = valeurs_ex[2, ], Chile = valeurs_ex[3, ])
# Convertir en format "long"
df_long <- df_large %>%
pivot_longer(cols = -Annee, names_to = "Pays", values_to = "Valeur")
df_long# A tibble: 6 × 3
Annee Pays Valeur
<dbl> <chr> <dbl>
1 2000 Argentina 1723
2 2000 Brasil 1353
3 2000 Chile 506
4 2001 Argentina 1823
5 2001 Brasil 1592
6 2001 Chile 602
La fonction map est une fonction puissante du package purrr du tidyverse en R. Elle permet d’appliquer une fonction à chaque élément d’une liste (ou d’un vecteur) et renvoie une nouvelle liste (ou vecteur) contenant les résultats de ces applications. C’est utile lorsque vous souhaitez effectuer des opérations répétitives sur des éléments de données, comme appliquer une fonction à chaque élément d’une liste ou d’un vecteur.
# Utilisation de map pour multiplier les valeurs par 2
df_long_2 <- df_long %>%
group_by(Pays) %>%
mutate(Valeur_multipliee = map_dbl(Valeur, ~ .x * 2))Plusieurs packages R sont utilisées pour ce projet. Les packages dans R sont des extensions de logiciels qui ajoutent des fonctionnalités spécifiques au langage R de base.
Ils sont conçus pour faciliter l’analyse de données, la visualisation, la modélisation statistique, et bien plus encore. Les packages sont comme des boîtes à outils virtuelles qui permettent aux utilisateurs d’effectuer des tâches analytiques avancées sans avoir à réinventer la roue à chaque fois. Ils permettent de gagner du temps et de se concentrer sur la résolution de problèmes spécifiques à son domaine d’étude, au lieu de vous soucier de la programmation de fonctions de base.
Lors de la rédaction de publications scientifiques, il est important de citer correctement les packages R utilisés dans votre analyse. Assurez-vous d’inclure le nom complet du package ainsi que le nom de son auteur ou des auteurs. Zotero et RStudio permettent aisément d’inclure ces citations dans votre analyse.
Les autres packages mobilisés dans pour ce cours sont listés dans le bloc de code ci-dessous :
library("tidyverse") # Une série de packages pour faciliter la manipulation de données
library("readxl") # Pour lire les fichiers excel (Carvalho et al. 2018)Warning: le package 'readxl' a été compilé avec la version R 4.2.3
library("writexl") # Pour écrire des fichiers excelWarning: le package 'writexl' a été compilé avec la version R 4.2.3
library("cowplot") # Pour arranger des graphiques en illustrations composéesWarning: le package 'cowplot' a été compilé avec la version R 4.2.3
Attachement du package : 'cowplot'
L'objet suivant est masqué depuis 'package:lubridate':
stamp
library("gt") # Pour des rendus graphiques harmonisés html et pdf/LaTeXWarning: le package 'gt' a été compilé avec la version R 4.2.3
library("sf") # Pour faciliter la manipulation de données géographiquesWarning: le package 'sf' a été compilé avec la version R 4.2.3
Linking to GEOS 3.9.3, GDAL 3.5.2, PROJ 8.2.1; sf_use_s2() is TRUE
library("wdpar") # Pour télécharger simplement la base d'aires protégées WDPAWarning: le package 'wdpar' a été compilé avec la version R 4.2.3
library("webdriver") # requis pour installer phantomjs pour wdparWarning: le package 'webdriver' a été compilé avec la version R 4.2.3
library("tmap") # Pour produire de jolies carteWarning: le package 'tmap' a été compilé avec la version R 4.2.3
The legacy packages maptools, rgdal, and rgeos, underpinning this package
will retire shortly. Please refer to R-spatial evolution reports on
https://r-spatial.org/r/2023/05/15/evolution4.html for details.
This package is now running under evolution status 0
library("geodata") # Pour télécharger simplement les frontières administrativesWarning: le package 'geodata' a été compilé avec la version R 4.2.3
Le chargement a nécessité le package : terra
Warning: le package 'terra' a été compilé avec la version R 4.2.3
terra 1.7.29
Attachement du package : 'terra'
L'objet suivant est masqué depuis 'package:tidyr':
extract
library("tidygeocoder") # pour obtenir les coordo GPS d'un point à partir de son nomWarning: le package 'tidygeocoder' a été compilé avec la version R 4.2.3
library("maptiles") # Pour télécharger des fonds de carte Warning: le package 'maptiles' a été compilé avec la version R 4.2.3
library("mapme.biodiversity") # Acquisition et traitement des données du projet
library("plm") # Linear Models for Panel Data and robust covariance matricesWarning: le package 'plm' a été compilé avec la version R 4.2.3
Attachement du package : 'plm'
Les objets suivants sont masqués depuis 'package:dplyr':
between, lag, lead
library("broom") # pour reformater simplement les rendus de tests statistiquesWarning: le package 'broom' a été compilé avec la version R 4.2.3
library("stargazer") # Reformater de manière plus lisible les résumé des régressions
Please cite as:
Hlavac, Marek (2022). stargazer: Well-Formatted Regression and Summary Statistics Tables.
R package version 5.2.3. https://CRAN.R-project.org/package=stargazer
library("MatchIt") # Pour le matchingWarning: le package 'MatchIt' a été compilé avec la version R 4.2.3
#library("glm") # Modèles linéaires généralisés (pour le PSM)
library("optmatch") # Fonctions d'optimisation du matchingWarning: le package 'optmatch' a été compilé avec la version R 4.2.3
library("did") # Méthode de double différence échelonnée de Callaway et Sant'AnnaWarning: le package 'did' a été compilé avec la version R 4.2.3
library("mapme.biodiversity")
library("cobalt") # Tables et graphs d'équilibre des groupes de matchingWarning: le package 'cobalt' a été compilé avec la version R 4.2.3
cobalt (Version 4.5.1, Build Date: 2023-04-27)
Attachement du package : 'cobalt'
L'objet suivant est masqué depuis 'package:MatchIt':
lalonde
En très bref :
Voir cette page pour un topo sur les imports. [#TODO:Préciser l’url]
Les études sur les aires protégées s’appuient fréquemment sur la base WDPA (World Database on Protected Area), consultable en ligne sur https://protectedplanet.net. On s’aperçoit, dans le cas de Madagascar, que cette base de données comporte de nombreuses erreurs (qu’on étudiera plus bas). La base rassemblée par l’association Vahatra dans le cadre de la monographie qu’elle a coordonnée sur l’ensemble des aires protégées terrestres malgaches semble beaucoup plus fiable [@goodman_les_2018]. Les données en question sont disponibles sur le portail https://protectedareas.mg avec une licence creative commons (CC-BY).
Le bloc de code ci-dessous (cliquer sur “code” pour visualiser), propose différentes d’opérations pour explorer, épurer et préparer les données avant analyse.
Pour comprendre certaines opérations contenues dans le bloc de code, il est utile d’être familier de la syntaxe de R et des packages du tidyverse. Voir le chapitre Section 1.
library(tidyverse)
library(lubridate)
library(sf)
library(tmap)
library(geodata)
library(cowplot)
library(wdpar)
library(gt)
library(readxl)
# On enregistre la table attributaire comme nouvel objet
AP_Vahatra <- read_xlsx("data/Vahatra/ch1_AP_Vahatra.xlsx")
# On prend connaissance des différentes variables avec le nom des colonnes
colnames(AP_Vahatra) [1] "nom" "cat_iucn" "creation"
[4] "date_creation" "date_modification" "mention_changement"
[7] "hectares" "num_atlas_" "full_name"
[10] "province" "region" "district"
[13] "gest_1" "gest_2" "type_ap"
[16] "an_creation" "nom_wdpa" "geometry"
[19] "rownum"
# On peut aussi faire apparaître le nom des 10 premières aires protégées et leur catégorie IUCN
AP_Vahatra %>%
select(nom, cat_iucn) %>%
filter(row_number() <= 10) %>%
gt()| nom | cat_iucn |
|---|---|
| Agnakatrika | VI |
| Agnalazaha | VI |
| Ambatofotsy | V |
| Ambatotsirongorongo | V |
| Ambatovaky | IV |
| Ambohidray | NA |
| Ambohijanahary | IV |
| Ambohitantely | IV |
| Ambohitr'Antsingy Montagne des Français | V |
| Amoron'i Onilahy | V |
Exercices : à l’aide des fonctions du tidyverse 1. Faire apparaître le nom des parcs nationaux de catégorie II “list_PN” 2. Créer une colonne avec la superficie de chaque aire en km2
# On fait apparaître le nom des parcs nationaux
liste_PN <- AP_Vahatra %>%
filter(cat_iucn == "II") %>%
select(nom)
# Création d'une colonne pour la superficie en km²
AP_Vahatra <- AP_Vahatra %>%
mutate(superficie_km2 = hectares * 0.01)On peut continuer à arranger les données en fonction des variables de notre choix, en l’occurence si la superficie en km² nous intéresse :
# Tri des données de manière décroissante en fonction de la superficie en km²
AP_Vahatra <- AP_Vahatra %>%
arrange(desc(superficie_km2))
# Obtenir les 3 plus grandes aires protégées
AP_Vahatra %>%
slice_head(n = 3) %>%
select(nom)# A tibble: 3 × 1
nom
<chr>
1 Complexe Zones Humides Mangoky Ihotry
2 Makira
3 Corridor Ankeniheny Zahamena
# Obtenir la superficie totale de toutes les aires protégées
AP_Vahatra %>%
summarise(sum(AP_Vahatra$superficie_km2))# A tibble: 1 × 1
`sum(AP_Vahatra$superficie_km2)`
<dbl>
1 63725.
# Résumé statistique des superficies en km²
summary(AP_Vahatra$superficie_km2) Min. 1st Qu. Median Mean 3rd Qu. Max.
2.249 46.061 249.625 650.253 758.975 4265.942
Exercices : à l’aide des fonctions du tidyverse 1. Combien il y a-t-il d’aires protégées qui ont une surface plus grande que le 3ème quartile ? 2. Quel est le nom des aires protégées créées après 2000 et dont la gestion est assurée par l’Etat ?
Si on s’intéresse par exemple à 2 variables : “superficie” et “catégorie IUCN”. On peut calculer, pour chaque catégorie, la superficie totale d’aires protégées pour avoir une vue d’ensemble.
# Calcul des superficies totales pour chaque catégorie IUCN
AP_Vahatra_iucn <- AP_Vahatra %>%
filter(!is.na(cat_iucn)) %>%
group_by(cat_iucn) %>%
summarise(superficie_totale = sum(superficie_km2))
# Production d'un joli tableau synthétique
AP_Vahatra_iucn %>%
mutate(superficie_totale = round(superficie_totale, 2)) %>% # Arrondir les km²
gt(AP_Vahatra_iucn) %>%
cols_label(
cat_iucn = "Catégorie IUCN",
superficie_totale = "Superficie totale (km²)"
) %>%
tab_header(
title = "Aires protégées de Madagascar : superficies par catégorie IUCN"
) %>%
tab_source_note(
"Source : données de l'association Vahatra"
)Warning in !is.null(rowname_col) && rowname_col %in% colnames(data_tbl):
‘length(x) = 2 > 1’ dans la conversion automatique vers ‘logical(1)’
| Aires protégées de Madagascar : superficies par catégorie IUCN | |
| Catégorie IUCN | Superficie totale (km²) |
|---|---|
| I | 22.40 |
| II | 25380.56 |
| III | 44.17 |
| IV | 4138.88 |
| V | 22752.70 |
| VI | 8265.72 |
| Source : données de l'association Vahatra | |
On commence par télécharger et présenter ces données.
# On regarde si les données WDPA sont disponibles sur l'ordinateur qui exécute
if (file.exists("data/WDPA/WDPA_Oct2023_MDG-shapefile.zip")) {
# Si oui, on charge
WDPA_Mada <- wdpa_read("data/WDPA/WDPA_Oct2023_MDG-shapefile.zip")
} else {
# Si non, on télécharge depuis protected planet
WDPA_Mada <- wdpa_fetch("Madagascar", wait = TRUE,
download_dir = "data/WDPA")
}
# On prend connaissance des différentes variables
colnames(WDPA_Mada) [1] "WDPAID" "WDPA_PID" "PA_DEF" "NAME" "ORIG_NAME"
[6] "DESIG" "DESIG_ENG" "DESIG_TYPE" "IUCN_CAT" "INT_CRIT"
[11] "MARINE" "REP_M_AREA" "REP_AREA" "NO_TAKE" "NO_TK_AREA"
[16] "STATUS" "STATUS_YR" "GOV_TYPE" "OWN_TYPE" "MANG_AUTH"
[21] "MANG_PLAN" "VERIF" "METADATAID" "SUB_LOC" "PARENT_ISO"
[26] "ISO3" "SUPP_INFO" "CONS_OBJ" "geometry"
Exercice : trouver signification de ces noms de colonnes, que représentent-elles réellement ? Ces données sont-elles fiables ?
Une technique pour connaître la fiabilité des données est de recenser les valeurs manquantes. L’ensemble peut être synthétisé sous forme de tableau.
# # Résumé des valeurs manquantes
#
# WDPA_Mada %>%
# summarise(`Nombre total d'aires protégées` = n(),
# `Catégorie IUCN manquante` = sum(IUCN_CAT == "Not Reported"),
# `Année de création manquante` = sum(STATUS_YR == 0),
# `Gestionnaire manquant` = sum(MANG_AUTH == "Not Reported")) %>%
# pivot_longer(cols = everything(),
# names_to = " ",
# values_to = "Nombre d'aires") %>%
# gt() %>%
# tab_header("Valeurs manquantes dans les données WDPA pour Madagascar") %>%
# tab_source_note("Source : WDPA (octobre 2023)")Exercice : combien il y a-t-il d’aires protégées au total dans le jeu de données Vahatra et dans celui du WDPA ? Combien de données manquantes ?
On peut également comparer ceux pour lesquels on a des différences de date ou de statut.
#Discussion comment vous feriez pour comparer ces deux jeux de données Pause du midi, comparaison
# Les librairies requises
library(sf) # pour traiter des données spatiales
library(tmap) # pour faire des cartes
library("wdpar") # Pour télécharger simplement la base d'aires protégées WDPA
# On regarde si les données WDPA sont disponibles sur l'ordinateur qui exécute
if (file.exists("data/WDPA/WDPA_Oct2023_MDG-shapefile.zip")) {
# Si oui, on charge
WDPA_Mada <- wdpa_read("data/WDPA/WDPA_Oct2023_MDG-shapefile.zip")
} else {
# Si non, on télécharge depuis protectedplanet
WDPA_Mada <- wdpa_fetch("Madagascar", wait = TRUE,
download_dir = "data/WDPA")
}
# On projette la carte
tm_shape(WDPA_Mada) +
tm_polygons(col = "IUCN_CAT") +
tmap_options(check.and.fix = TRUE) + # Parce qu'on a quelques erreurs topo
tm_layout(legend.outside = TRUE)
(projection de la carte, obligatoire de faire st_make_valid ?)
On utilise le package ggplot, avec la syntaxe suivante.
# On réalise un graphique simple
WDPA_Mada %>%
ggplot(aes(x = IUCN_CAT, y = REP_AREA)) +
geom_col()
Si maintenant on s’intéresse à la dynamique de création d’aires protégées, on peut croiser les données correspondant à l’année de création avec celles de superficie.
# Calcul de la superficie cumulée en fonction des années
AP_superficie_annees <- AP_Vahatra %>%
group_by(an_creation) %>% # On regroupe d'abord les AP qui ont été créées la même année
summarise(superficie_cumulée = sum(superficie_km2)) %>% # On fait la somme de ces superficies (par année de création)
mutate(superficie_cumulée = cumsum(superficie_cumulée)) # Pour le rendu graphique (cumulatif), on accumule les superficies de chaque groupe (année de création X) avec le groupe précédent (X -1)
## Création d'un graphique de dispersion linéaire (points et ligne de raccordement)
ggplot(data = AP_superficie_annees, aes(x = an_creation, y = superficie_cumulée)) +
geom_point() +
geom_line() +
labs(x = "Année de création de l'aire protégée", y = "Superficie cumulée (km²)") +
ggtitle("Superficie cumulée en fonction de l'année de création") +
theme_minimal()
Le bloc de code suivant génère une carte interactive. On a également inclus des lignes de code qui permettent de formater la carte joliment pour un rendu figé (pdf/LaTeX, html statique, word), mais ce code est “commenté”, c’est-à-dire qu’on a placé des dièses au début de chaque ligne, de sorte qu’il ne s’exécute pas (R n’exécute jamais ce qui se trouve à droite d’un # sur une ligne). Pour plus de détails sur la manière dont on produit des cartes, voire la section “Cartes simples avec R” dans le chapitre Section 1.
## Faire apparaître les aires protégées WDPA non présentes dans Vahatra
WDPA_exclu <- WDPA_Mada %>%
filter(!(NAME %in% AP_Vahatra$nom_wdpa))
tmap_mode("view")tmap mode set to interactive viewing
WDPA_exclu %>%
tm_shape() +
tm_polygons(col = "IUCN_CAT")On va représenter le jeu de données Vahatra avec les frontières de Madagascar.
# On regarde si les frontières terrestres de Mada ont déjà été téléchargées
if (file.exists("data/contour_mada.rds")) {
# Si c'est le cas, on charge la version déjà disponible localement
load("data/contour_mada.rds")
} else {
# Sinon on la télécharge depuis la base GADM
contour_mada <- gadm(country = "Madagascar", resolution = 1, level = 0,
path = "data/GADM") %>%
st_as_sf()
# On enregistre contour_mada pour s'en servir par la suite
save(contour_mada, file = "data/contour_mada.rds")
}
# On génère un rendu cartographique
# tmap_mode("view") # En mode interactif
# tm_shape(contour_mada) +
# tm_borders() +
# tm_shape(AP_Vahatra) +
# tm_polygons(col = "cat_iucn", alpha = 0.6, title = "Catégorie IUCN",
# id = "nom",
# popup.vars = c("Acte de création" = "creation",
# "Année de création" = "an_creation",
# "Surface (ha)" = "hectares",
# "Nom complet" = "full_name",
# "Gestionnaire" = "gest_1")) +
# tmap_options(check.and.fix = TRUE)Exercice : reproduire la carte avec les données WDPA
tm_shape(contour_mada) +
tm_borders() +
tm_shape(WDPA_Mada) +
tm_polygons(col = "IUCN_CAT", alpha = 0.6, title = "Catégorie IUCN",
id = "NAME",
popup.vars = c("Type" = "DESIG",
"Catégorie UICN" = "IUCN_CAT",
"Surface déclarée" = "REP_AREA",
"Année du statut" = "STATUS_YR")) +
tmap_options(check.and.fix = TRUE)